/**
 * 
 */
package escola.web.filters;

import java.io.IOException;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;
import org.springframework.web.filter.GenericFilterBean;

import escola.spring.datasource.DataSourceContextHolder;
import escola.spring.datasource.DataSourceRouter;
import escola.spring.datasource.exception.InvalidUserNameException;

/**
 * @author Jonathan
 *
 */
public class DataSourceFilter extends GenericFilterBean {

	private static final String DATA_SOURCE_BEAN = "dataSource" ;
	
	private static final String DATA_SOURCE_NAME = "dataSourceRouterName";
	
	private static final String FAILURE_URL = "/accessFail.do";
	
	@Override
	public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
		try {
			String dataSourceName = getDataSourceName(request);
			if (dataSourceName != null) {
				DataSourceContextHolder.setDataSourceName(dataSourceName);
			}
			chain.doFilter(request, response);
		} catch (InvalidUserNameException e){
			sendRedirect((HttpServletRequest)request, (HttpServletResponse)response);
		}
	}

	private void sendRedirect(HttpServletRequest request, HttpServletResponse response) throws IOException {
		String failureUrl = request.getContextPath() + FAILURE_URL;
		response.sendRedirect(response.encodeRedirectURL(failureUrl));
	}

	private String getDataSourceName(ServletRequest request) {
		String userName = request.getParameter(UsernamePasswordAuthenticationFilter.SPRING_SECURITY_FORM_USERNAME_KEY);
		if (userName != null) {
			String database = getDatabaseName(userName);
			if (database == null) {
				throw new InvalidUserNameException();
			}
			initDatabase(request, database);
		}
		return (String) getSession(request).getAttribute(DATA_SOURCE_NAME);
	}

	private void initDatabase(ServletRequest request, String database) {
		if (!lookupDataSourceRouter().hasDatabases(database)) {
			throw new InvalidUserNameException();
		}
		getSession(request).setAttribute(DATA_SOURCE_NAME, database);
	}
	
	
	private HttpSession getSession(ServletRequest request) {
		return ((HttpServletRequest)request).getSession();
	}

	private String getDatabaseName(String userName) {
		if (userName.indexOf("@") > -1) {
			return userName.substring(userName.indexOf("@") + 1);
		}
		return null;
	}
	
	private DataSourceRouter lookupDataSourceRouter() {
		WebApplicationContext wac = WebApplicationContextUtils.getRequiredWebApplicationContext(getServletContext());
		return wac.getBean(DATA_SOURCE_BEAN, DataSourceRouter.class);
	}

}
